﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using Org.Flowertwig.Media.Information.Services;

namespace Org.Flowertwig.Media.Services.LocalService
{
    public class IndexingService : ISource
    {
        protected Thread _thread;
        private static string SpecialDirSample = Path.DirectorySeparatorChar + "Sample";
        private static string SpecialDirSubs = Path.DirectorySeparatorChar + "Subs";

        public static Service ServiceKey
        {
            get
            {
                return new Service
                           {
                               Id = "LS",
                               Name = "LocalService",
                               ApplicationPathAndName = typeof(IndexingService).Assembly.Location
                           };
            }
        }

        public IndexingService()
        {
            Console.WriteLine("IndexingService");
            _thread = new Thread(OnStart);
        }

        public void Start()
        {
            Console.WriteLine("# Starting");
            _thread.Start();
        }

        protected void FindPotentialFilesInDirectory(string dir)
        {
            try
            {
                var releases = new List<Information.Media>();
                var files = Directory.GetFiles(dir);
                foreach (var file in files)
                {
                    // This is a archive, do we have any interesting files in it?
                    if (file.EndsWith(".rar"))
                    {
                        // Ignore all part**.rar files except part01.rar
                        const string rarPart = @".*part(?<Part>[0-9]{2})\.rar$";

                        Match m = Regex.Match(file, rarPart);
                        if (m.Success && m.Groups.Count == 2)
                        {
                            string partNumber = m.Groups["Part"].Value.ToLower();
                            if (!string.Equals("01", partNumber))
                                continue;
                        }

                        if (Regex.IsMatch(file, @".*part[0-9](0|[2-9])\.rar$"))
                            continue;

                        var archiveHandler = new ArchiveHandler(Properties.Settings.Default.SevenZipPath);
                        var archive = archiveHandler.ListFilesInArchive(file);

                        foreach (var archiveItem in archive.Items)
                        {
                            string itemName = archiveItem.Name;
                            var isKnownFileType = itemName.EndsWith(".avi")
                                                  || itemName.EndsWith(".img")
                                                  || itemName.EndsWith(".mkv");

                            if (isKnownFileType)
                            {
                                // Add archive to handable files if 'isKnownFileType' is true.
                                releases.Add(CreateRelease(file, true));
                            }
                        }
                    }
                    else if (file.EndsWith(".avi")
                                          || file.EndsWith(".img")
                                          || file.EndsWith(".mkv"))
                    {
                        // Add file to handable files (So we can handle it in a seperate thread.
                        // We only want to find files in this thread, not collect info and stuff.
                        releases.Add(CreateRelease(file, false));
                    }
                }

                Storage.AddMedias(ServiceKey, releases);

                var subDirectories = Directory.GetDirectories(dir);
                foreach (var subDirectory in subDirectories)
                {
                    var isSpecialDirectory = subDirectory.EndsWith(SpecialDirSample, StringComparison.CurrentCultureIgnoreCase)
                                             || subDirectory.EndsWith(SpecialDirSubs, StringComparison.CurrentCultureIgnoreCase);

                    if (isSpecialDirectory)
                    {
                        // Find special files

                    }
                    else
                    {
                        FindPotentialFilesInDirectory(subDirectory);
                    }
                }
            }
            catch (Exception)
            {
            }
        }

        protected Information.Media CreateRelease(string filename, bool requireProcessBeforePlay)
        {
            return new Information.Media
                       {
                           Name = filename,
                           RequireProcessBeforePlay = requireProcessBeforePlay,
                           InternalServiceId = filename
                       };
        }

        protected void OnStart()
        {
            var sources = Properties.Settings.Default.Sources;

            Storage.AddService(ServiceKey);

            foreach (var source in sources)
            {
                FindPotentialFilesInDirectory(source);
            }
        }

        public void Stop()
        {
            if (_thread != null)
            {
                //Console.WriteLine("Stopping server.");
                _thread.Abort();
            }
        }
    }
}
